﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetfractionHub.Network.Protocol;
using NetfractionHub.Network.Protocol.BASE.Factory;

namespace NetfractionHub.LocalMachine.BotCommands.Handler
{
    [CommandHandler("reguser")]
    public class RegisterUser : CommandHandler
    {
        public override BotReturnStatus HandleCommandMessage(NetfractionHub.RemoteMachine.Node source, CommandMessage message)
        {
            if (message.StringArguments.Count == 1)
                if (message.StringArguments.ContainsKey("user"))
                    return SendRegisterMessage(source, message.StringArguments["user"]);
            else if (message.StringArguments.Count == 2)
            {
                if (!message.StringArguments.ContainsKey("user"))
                    return new BotReturnStatus(false, "Missing argument 'user'.");

                if (!message.StringArguments.ContainsKey("cid"))
                    return new BotReturnStatus(false, "Missing argument 'cid'.");

                bool nodeOffline = false;
                if (message.BooleanArguments.ContainsKey("offline"))
                    nodeOffline = true;

                return RegisterNodeWithoutPassword(source, message.StringArguments["user"], message.StringArguments["cid"], nodeOffline);
            }
            else if (message.UnnamedArguments.Count == 1)
                return SendRegisterMessage(source, message.UnnamedArguments[0]);
            else
                return false;

            return true;
        }

        private BotReturnStatus RegisterNodeWithoutPassword(NetfractionHub.RemoteMachine.Node source, string username, string clientId, bool nodeOffline)
        {
            RemoteMachine.Node userNode = null;
            if (!nodeOffline)
                userNode = Network.ConnectionManager.GetConnectedNodeByClientId(clientId);
            
            if (userNode != null)
            {
                if (!Security.Permission.HasPermission(source.SecurityIdentity, typeof(Security.Permissions.RegisterUserPermission)))
                    return new BotReturnStatus(false, Security.Permission.GetDeniedString(typeof(Security.Permissions.RegisterUserPermission)));

                if (!Security.RoleManager.IsInAncestorTree(source.SecurityIdentity.Role, userNode.SecurityIdentity.Role))
                    return new BotReturnStatus(false, string.Format("Permission denied. You are not an ancestor of '{0}'.", username));

                if (userNode.SecurityIdentity.IsRegistered)
                    return new BotReturnStatus(false, string.Format("The user '{0}' is already registered.", username));

                this.ParentBot.SendPrivateMessageFromBot(userNode, "Please enter a password to register your account using the !pass command. You must remember this password to connect to the hub.\nUsage: !pass \"newpassword\"");
                userNode.SecurityIdentity.NewPasswordRequestActive = true;
                return true;
            }
            else if (nodeOffline)
            {
                if (!Security.Permission.HasPermission(source.SecurityIdentity, typeof(Security.Permissions.RegisterUserPermission)))
                    return new BotReturnStatus(false, Security.Permission.GetDeniedString(typeof(Security.Permissions.RegisterUserPermission)));

                if (Security.IdentityManager.GetIdentityByClientId(clientId) != null)
                    return new BotReturnStatus(false, string.Format("The user '{0}' is already registered.", username));

                // RoleId == 4 == Registered User. What if the Id doesn't exist?
                Security.Identity newIdent = Security.Identity.CreateGenericIdentityForRole(Security.RoleManager.GetRoleById(4));
                if (newIdent != null)
                {
                    newIdent.Name = username;
                    newIdent.ClientId = clientId;
                    newIdent.IsRegistered = true;
                    bool regSuccess = Security.IdentityManager.RegisterIdentity(newIdent);
                    if (regSuccess)
                        this.ParentBot.SendEchoMessageFromBot(source, "Registration Successful.");

                    return regSuccess;
                }
            }
            else
                return new BotReturnStatus(false, string.Format("Cannot register user, the user '{0}' does not exist.", username));

            return false;
        }

        private BotReturnStatus SendRegisterMessage(NetfractionHub.RemoteMachine.Node source, string username)
        {
            RemoteMachine.Node user = Network.ConnectionManager.GetConnectedNodeByNickname(username);
            if (user == null)
                return new BotReturnStatus(false, string.Format("Cannot register user, the user '{0}' does not exist.", username));

            if (!Security.Permission.HasPermission(source.SecurityIdentity, typeof(Security.Permissions.RegisterUserPermission)))
                return new BotReturnStatus(false, Security.Permission.GetDeniedString(typeof(Security.Permissions.RegisterUserPermission)));

            if (Security.RoleManager.IsInAncestorTree(source.SecurityIdentity.Role, user.SecurityIdentity.Role))
                return new BotReturnStatus(false, string.Format("Permission denied. You are not an ancestor of '{0}'.", username));
            
            if (user.SecurityIdentity.IsRegistered)
                return new BotReturnStatus(false, string.Format("The user '{0}' is already registered.", username));
                
            this.ParentBot.SendPrivateMessageFromBot(user, "Please enter a password to register your account using the !pass command. You must remember this password to connect to the hub.\nUsage: !pass \"newpassword\"");

            user.SecurityIdentity.NewPasswordRequestActive = true;
            return new BotReturnStatus(true);
        }
    }
}
